////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBotUnitTests\TestPowerTreeNode.h
///
/// @brief  Defines tests for the CollabRC::Bot::AI::PowerTreeNode class
////////////////////////////////////////////////////////////////////////////////////////////////////

#include <cxxtest/TestSuite.h>
#include "../CollabRCBot/PowerTreeNode.h"
#include "../CollabRCBot/exceptions.h"
#include "MockConstantTreeNode.h"
#include "MockOperationTreeNode.h"

class TestPowerTreeNode : public CxxTest::TestSuite
{
private:
    MockConstantTreeNode m_lhs, m_rhs;
    CollabRC::Bot::AI::PowerTreeNode m_ptn;
public:
    TestPowerTreeNode():m_lhs(2),m_rhs(5),m_ptn(m_lhs,m_rhs)
    {
    }

    /**
     * @brief Tests the implementation of CollabRC::Bot::AI::PowerTreeNode::PerformOperation
     */
    void TestPerformOperation()
    {
        // Basic tests
        TS_ASSERT_EQUALS(m_ptn.PerformOperation(2.0f, 5.0f), 32.0f);    // 2^5 = 32
        TS_ASSERT_EQUALS(m_ptn.PerformOperation(16.0f, 0.5f), 4.0f);    // sqrt(16) = 4
        TS_ASSERT_EQUALS(m_ptn.PerformOperation(0.5f, -2.0f), 4.0f);    // 0.5^-2 = 1/0.5^2 = 1/0.25 = 4
        TS_ASSERT_EQUALS(m_ptn.PerformOperation(-2.0f, 4.0f), 16.0f);   // (-2)^4 = 16

        // Verify sqrt(negative) is illegal
        TS_ASSERT_THROWS(m_ptn.PerformOperation(-16.0f, 0.5f), const CollabRC::Bot::AI::IllegalOperationException&);
    }

    /** @brief Verifies the operation of CollabRC::Bot::AI::PowerTreeNode::Clone */
    void TestClone()
    {
        CollabRC::Bot::AI::PowerTreeNode* clone = dynamic_cast<CollabRC::Bot::AI::PowerTreeNode*>(m_ptn.Clone());
        TS_ASSERT(clone != NULL);                               // Verify type
        TS_ASSERT_EQUALS(clone->Compute(), m_ptn.Compute());    // Verify consistency
        TS_ASSERT_THROWS_NOTHING(delete clone);                 // Verify on heap
    }

    /** @brief Tests the copy constructor that ensures mutation operations can occur */
    void TestMutateTo()
    {
        CollabRC::Bot::AI::PowerTreeNode node(m_lhs, m_rhs);
        MockOperationTreeNode mockOp(m_lhs, m_rhs);
        CollabRC::Bot::AI::PowerTreeNode mutation(mockOp);
        TS_ASSERT_EQUALS(node.Compute(), mutation.Compute());
    }
};